package org.wisdom.data.jpa.repository;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.hibernate.cfg.InheritanceState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.wisdom.data.jpa.entity.ObjectEntity;
import org.wisdom.data.jpa.entity.WisdomEntity;
import org.wisdom.exception.BusinessException;

/**
 * @author zhangzhiyan
 * @date 2022/04/15 12:57
 **/
@SuppressWarnings("NullableProblems")
public class WisdomRepositoryImpl<T extends ObjectEntity, K extends Serializable> extends SimpleJpaRepository<T, K>
    implements WisdomRepository<T, K> {

    private final EntityManager entityManager;

    private final JpaEntityInformation<T, K> entityInformation;

    private final Class<T> clazz;

    @Autowired(required = false)
    public WisdomRepositoryImpl(JpaEntityInformation<T, K> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.clazz = entityInformation.getJavaType();
        this.entityManager = entityManager;
        this.entityInformation = entityInformation;
        InheritanceState s;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void logicalDeleteById(K id) {
        T t = this.findById(id).orElseThrow(() -> new EmptyResultDataAccessException(
            String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1));
        if (t instanceof WisdomEntity) {
            ((WisdomEntity)t).setDelFlag(true);
            this.entityManager.persist(t);
        } else {
            throw new BusinessException("逻辑删除实体必须继承CommonEntity");
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public int executeUpdate(String jpql, Object... params) {
        Query query = this.entityManager.createQuery(jpql);
        if (params != null) {
            for (int i = 0; i < params.length; ++i) {
                query.setParameter(i + 1, params[i]);
            }
        }
        return query.executeUpdate();
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public int executeUpdate(String jpql, Map<String, Object> params) {
        Query query = this.entityManager.createQuery(jpql);
        if (params != null) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                query.setParameter(key, params.get(key));
            }
        }
        return query.executeUpdate();
    }

    /**
     * 重写保存方法，更新时，null字段不进行更新
     *
     * @author 张智研
     * @date 2022/06/09 10:23
     * @param entity 实体
     * @return S 实体
     */
    @Override
    public <S extends T> S save(S entity) {
        Assert.notNull(entity, "Entity must not be null.");

        if (entityInformation.isNew(entity)) {
            entityManager.persist(entity);
            return entity;
        } else {
            return entityManager.merge(entity);
        }
    }

    /**
     * 获取类
     * @author 张智研
     * @date 2022/06/09 15:23
     * @return java.lang.Class<T>
     */
    public Class<T> getClazz() {
        return clazz;
    }
}